package log

import (
	"fmt"
	"io"
	"os"
	"strings"
	"sync"
	"time"

	rotatelogs "github.com/lestrrat-go/file-rotatelogs"
	"github.com/rifflock/lfshook"
	"github.com/sirupsen/logrus"
)

var once sync.Once

// 日志模块 使用logrus
// logrus初始化配置
func InitLog() {
	once.Do(func() {
		logrus.SetLevel(logrus.InfoLevel)
		//logrus.SetFormatter(&logrus.TextFormatter{})
		logrus.SetFormatter(&MyFormatter{})

		//设置output,默认为stderr,可以为任何io.Writer，比如文件*os.File
		//file, err := os.OpenFile("blog-project-go.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
		writers := []io.Writer{
			//file,
			os.Stdout}
		//同时写文件和屏幕
		fileAndStdoutWriter := io.MultiWriter(writers...)
		logrus.SetOutput(fileAndStdoutWriter)

		// 添加钩子
		hook := NewLfsHook()
		logrus.AddHook(hook)
		logrus.Info("logrus初始化配置完成")
	})

}

// MyFormatter 自定义日志格式 实现logrus.Formatter接口
type MyFormatter struct{}

// Format 实现Format方法
func (s *MyFormatter) Format(entry *logrus.Entry) ([]byte, error) {
	timestamp := time.Now().Local().Format("2006-01-02 15:04:05")
	msg := fmt.Sprintf("%s [%s] %s\n", timestamp, strings.ToUpper(entry.Level.String()), entry.Message)
	return []byte(msg), nil
}

// NewLfsHook 日志钩子(日志拦截，并重定向)
func NewLfsHook() logrus.Hook {

	// 可设置按不同level创建不同的文件名
	lfsHook := lfshook.NewHook(lfshook.WriterMap{
		logrus.TraceLevel: createLogWriter(logrus.TraceLevel),
		logrus.DebugLevel: createLogWriter(logrus.DebugLevel),
		logrus.InfoLevel:  createLogWriter(logrus.InfoLevel),
		logrus.WarnLevel:  createLogWriter(logrus.WarnLevel),
		logrus.ErrorLevel: createLogWriter(logrus.ErrorLevel),
		logrus.FatalLevel: createLogWriter(logrus.FatalLevel),
		logrus.PanicLevel: createLogWriter(logrus.PanicLevel),
	}, &MyFormatter{})

	return lfsHook
}

func createLogWriter(level logrus.Level) io.Writer {
	writer, err := rotatelogs.New(
		// 日志文件
		//logName+".%Y%m%d%H%M%S",
		"logs/%Y-%m-%d/"+level.String()+".log",

		// 日志周期(默认每86400秒/一天旋转一次)
		//rotatelogs.WithRotationTime(time.Second * 2),
		// 清除历史 (WithMaxAge和WithRotationCount只能选其一)
		//rotatelogs.WithMaxAge(time.Hour*24*30), //默认每7天清除下日志文件
		rotatelogs.WithRotationCount(60), //只保留最近的N个日志文件
	)
	if err != nil {
		panic(err)
	}
	return writer
}
